package com.aorise.controller.system;

import com.aorise.exception.DataValidationException;
import com.aorise.model.system.User;
import com.aorise.model.response.LoginUserRes;
import com.aorise.utils.ConstDefine;
import com.aorise.utils.DataValidation;
import com.aorise.utils.StatusDefine;
import com.aorise.utils.StatusDefineMessage;
import com.aorise.utils.json.JsonResponseData;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

/**
 * @Auther: zhouhao
 * @Date: 2019/4/26
 * @Description:
 */
@Slf4j
@Api(description = "登录相关接口")
@RestController
@Validated
@RequestMapping("api/admin")
public class LoginController {

    /**
     * 系统登录
     * HTTP 方式：POST
     * API 路径：/api/admin/
     * 方法名：login
     * 方法返回类型：String
     */
    @ApiOperation(value = "用户登录", httpMethod = "POST", response = String.class, notes = "用户登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "account", value = "登录帐号",  paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "password", value = "登录密码",  paramType = "query", dataType = "String")
    })
    @RequestMapping(value = "/login", method = RequestMethod.POST,produces="application/json")
    public String login(String account,String password) {
        LoginUserRes req =null;
        DataValidation validation =new DataValidation();
        try {
            validation.chekeNotempty(account,"账号不支持为空，请完善资料");
            validation.chekeNotempty(password,"密码不支持为空，请完善资料");
        // 从SecurityUtils里边创建一个 subject
            Subject subject = SecurityUtils.getSubject();
            /**未填用户类型默认后台用户*/
            Integer userType =null;
            userType = userType==null? ConstDefine.USER_TYPE_SYS:userType;
            /**将用户类型与用户合并传到shiro中，根据用户类型获取用户信息*/
            String tokenAccount=account+"#"+userType;
            // 在认证提交前准备 token（令牌）
            UsernamePasswordToken token = new UsernamePasswordToken(tokenAccount, password);
            // 执行认证登陆
            subject.login(token);
            /**设置超时时间 单位ms*/
            SecurityUtils.getSubject().getSession().setTimeout(600000000);
            User user = (User) subject.getPrincipal();
            req = new LoginUserRes();
            BeanUtils.copyProperties(user,req);
            req.setToken((String) subject.getSession().getId());
        }catch (AuthenticationException e) {
            log.error(
                    "controller:LoginController. function:login...msg: login DataValidationException");
            log.error("error:" + e.getMessage());
            return new JsonResponseData(false, "", StatusDefine.U_PWD_FAILED,
                    StatusDefineMessage.GetMessage(StatusDefine.U_PWD_FAILED), null).toString();
        }catch (DataValidationException e) {
            log.error(
                    "controller:LoginController. function:login...msg: login DataValidationException");
            log.error("error:" + e.getMessage());
            return new JsonResponseData(false, "", StatusDefine.DATA_FORMAT_ERROR,
                    e.getMessage(), null).toString();
        }catch (DataAccessException e) {
            log.error(
                    "controller:LoginController. function:login...msg: login DataAccessException");
            log.error("error:" + e.getMessage());
            return new JsonResponseData(false, "", StatusDefine.DB_ERROR,
                    StatusDefineMessage.GetMessage(StatusDefine.DB_ERROR), null).toString();
        } catch (Exception e) {
            log.error(
                    "controller:LoginController. function:login. msg:login Exception");
            log.error(e.getMessage());
            return new JsonResponseData(false, "", StatusDefine.SYS_ERROR,
                    StatusDefineMessage.GetMessage(StatusDefine.SYS_ERROR), null).toString();
        }
        return JsonResponseData.ofSuccess(req);
    }

    @ApiIgnore
    @ApiOperation(value = "用户无操作权限", response = String.class, notes = "用户无操作权限")
    @RequestMapping(value = "/notRole",produces="application/json")
    public String unauthorized(){
        return new JsonResponseData(Boolean.TRUE, StatusDefineMessage.GetMessage(StatusDefine.PERMISSIONDENIED),
                StatusDefine.PERMISSIONDENIED, "", null).toString();
    }

    @ApiIgnore
    @ApiOperation(value = "用户未登录",response = String.class, notes = "用户未登录")
    @RequestMapping(value = "/notLogin",produces="application/json")
    public String notLogin(){
        return new JsonResponseData(Boolean.TRUE, StatusDefineMessage.GetMessage(StatusDefine.U_UNLOAD),
                StatusDefine.U_UNLOAD, "", null).toString();
    }

    /**
     * 用户登出
     * HTTP 方式：GET
     * API 路径：/api/admin/
     * 方法名：logout
     * 方法返回类型：String
     */
    @ApiOperation(value = "用户登出", httpMethod = "GET", response = String.class, notes = "用户登出")
    @RequestMapping(value = "/logout", method = RequestMethod.GET,produces="application/json")
    public String logout() {
        Subject subject =null;
        try{
             subject = SecurityUtils.getSubject();
            if(subject !=null){
                //注销
                subject.logout();
                return JsonResponseData.ofSuccess(null);
            }
        }catch (DataAccessException e) {
            log.error(
                    "controller:LoginController. function:logout...msg: logout DataAccessException");
            log.error("error:" + e.getMessage());
            return new JsonResponseData(false, "", StatusDefine.DB_ERROR,
                    StatusDefineMessage.GetMessage(StatusDefine.DB_ERROR), null).toString();
        } catch (Exception e) {
            log.error(
                    "controller:LoginController. function:logout. msg:logout Exception");
            log.error(e.getMessage());
            return new JsonResponseData(false, "", StatusDefine.SYS_ERROR,
                    StatusDefineMessage.GetMessage(StatusDefine.SYS_ERROR), null).toString();
        }
        return JsonResponseData.ofFailure();
    }
}
